package com.credit.mola.app.utils.event.track

import android.annotation.SuppressLint
import android.content.Context
import com.credit.mola.app.utils.log.HHLog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.coroutines.coroutineContext

/**
 * 埋点管理器
 */
@SuppressLint("StaticFieldLeak")
object TrackEventManager {
    private lateinit var dao: TrackEventDao
    private var trackUploader: TrackEventUploader = CreditMolaTrackEventUploader()

    // Coroutine Scope
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())

    /** 上传操作的互斥锁 */
    private val uploadMutex = Mutex()

    /** 释放任务的状态 */
    private var isDestroyed = AtomicBoolean(false)

    /** 当前在上传的任务 */
    private var currentUploadJob: Job? = null

    /** 初始化方法 */
    fun init(context: Context) {
        dao = TrackEventDatabase.getDatabase(context).eventDao()
        HHLog.d("TrackEventManager initialized")
    }

    /** 释放 */
    fun destroy() {
        if (isDestroyed.compareAndSet(false, true)) {
            scope.cancel()
            HHLog.d("TrackEventManager destroyed")
        }
    }

    /** 记录埋点事件 */
    fun trackEvent(type: String, remark: String?) {
        scope.launch(Dispatchers.IO) {
            val event = TrackEvent(type.uppercase(), remark)
            dao.insert(event)
            HHLog.d("TrackEventManager Event recorded: $type,$remark")
        }
    }

    /** 记录埋点事件，并立即上传 */
    fun trackEventNow(type: String, remark: String?) {
        scope.launch(Dispatchers.IO) {
            val event = TrackEvent(type = type.uppercase(), remark = remark)
            dao.insert(event)
            HHLog.d("TrackEventManager Event recorded: $type,$remark")

            performUpload()
        }
    }

    /** 主动上传未上传的埋点事件 */
    fun uploadEvents() {
        scope.launch(Dispatchers.IO) {
            try {
                if (!isActive) return@launch
                performUpload()
            } catch (e: Exception) {
                HHLog.d("TrackEventManager Manual upload failed: ${e.message}")
            }
        }
    }

    /** 通用的上传逻辑 */
    private suspend fun performUpload() {
        currentUploadJob?.cancel()
        if (!coroutineContext.isActive) return

        uploadMutex.withLock {
            if (!coroutineContext.isActive) return

            val events = dao.getUnsentEvents()
            if (events.isNotEmpty()) {
                currentUploadJob = scope.launch(Dispatchers.IO) {
                    retryWithBackoff(maxRetries = 3) {
                        val uploadJob = async { trackUploader.upload(events) }
                        val eventIds = events.map { it.id.toLong() }
                        val markJob = async {
                            dao.markAsUploaded(eventIds)
                            dao.deleteUploadedEvents(eventIds)
                        }

                        uploadJob.await()
                        markJob.await()
                        HHLog.d("TrackEventManager ${events.size} events as uploaded")
                    }
                }
            }
        }
    }

    /** 重试上传机制 */
    private suspend fun <T> retryWithBackoff(maxRetries: Int, initialDelayMillis: Long = 1000, block: suspend () -> T): T {
        var currentDelay = initialDelayMillis
        repeat(maxRetries - 1) {
            try {
                return block()
            } catch (e: Exception) {
                HHLog.d("TrackEventManager Retrying after failure: ${e.message}")
            }
            delay(currentDelay)
            currentDelay *= 2
        }
        return block()
    }
}